iT邦幫忙

2022 iThome 鐵人賽

DAY 7
1
Modern Web

致 JavaScript 開發者的 Functional Programming 新手指南系列 第 7

Day 7 :JavaScript 型別與他們的地雷(4):表達式與陳述式

  • 分享至 

  • xImage
  •  

相信各位 JavaScript 開發者,對表達式(Expression)與陳述式(statement)的概念不陌生,這兩個概念可以說是初階前端工程師必考的面試題,但這個概念為什麼重要到每間公司都要考你呢?也許看完以下的說明,就會知道表達式與陳述式的概念為什麼在 FP 很重要了。

常見的表達式

《Speaking JavaScript》 的作者 Dr. Axel Rauschmayer 曾在其部落格發表過一篇文章《Expressions versus statements in JavaScript》,在此文章中針對 JavaScript 表達式與陳述式的種類進行了詳盡的介紹,Dr. Axel Rauschmayer 針對這兩者的差異說道:「表達式會產生值,陳述式執行某些行為。」

聽起來是不是有點不直覺?不好理解呢?

老實說,在一開始自己擠也花了許久的時間來理解表達式與陳述式的概念,或許我們可以透過下方範例更了解什麼叫作「會產出值(回傳值)」的概念:

const a = 1;
console.log(a);
// 1

我們宣告一個變數,再次要取用變數時,會發現 a 變數會給我們一個預先存進去的值 1

此外,經驗告訴我們,變數的右側可不只能放純值、物件陣列,還可以進行運算:

const b = 1 + 1;
console.log(b);
// 2

由此可見,變數可以產出某種值,所以是一個經典表達式的例子。

換個方式思考,可以被存成變數的東西,一定要可以回傳某個值,才能被變數存起來,試想如果「值」本人如果不告訴變數自己帶有什麼樣的值,變數大概也無從判斷你想把什麼放進自己裡面吧?

因此,要可以被放進變數裡的東西,一定要是表達式!

所以除了基本型別、物件、陣列外,運算式也是一種表達式,包括短路計算(註一)、三元運算式本身也是一種會回傳值的 Expression 。

在前一個章節,我們聊到函式是「一等公民」,除了可以用來解決重複性的邏輯外我們更可以把函式看作一種「值」,所以函式也是一種表達式,在我們沒有主動回傳某個值時,JavaScript 就會自動幫我們的函式回傳 undefined

在後續的章節中,我們會看到更多、各式各樣的表達式。

常見的陳述式

當了解什麼是表達式後,了解什麼是陳述式就沒有那麼難了,如果我們用「會執行某個行為」來定義 陳述式,感覺有點不明確,難道你不覺得「回傳」也很像要執行某個動作嗎?

於是在觀察了眾多開發者的說法後,自己覺得直接把**陳述式定義成「不能直接賦予進變數中,或是做為參數使用」**似乎更好理解。

舉例來說:

  1. 流程判斷的 if…else…
  2. 流程判斷的 switch
  3. for 系列的迴圈
  4. 變數與函式的宣告(Variable statements & function Declaration)

以上這些 JavaScript 的語法,都沒有辦法被當成一個「獨立的值」賦予進變數內,或是做為參數使用,甚至我們常使用的 forEach 根本不能使用 return 關鍵字。

當然說到這邊你可能會發現:if…else… 或是 switch 也可以傳回傳某個值呀?

沒錯!Dr. Axel Rauschmayer 在文中提及:

「Wherever JavaScript expects a statement, you can also write an expression. Such a statement is called an expression statement. The reverse does not hold: you cannot write a statement where JavaScript expects an expression. For example, an if statement cannot become the argument of a function.」

在 JavaScript 中預期使用陳述式的地方,我們同樣也可以使用表達式取代,這樣的陳述我們稱其為「表達陳述式」,但要注意的是,表達陳述式除非有用函式額外包裝起來,不然同樣沒有辦法作為參數或是變數的值。

但如果反過來呢?是不是有「陳述表達式」這種概念?如果我們還記得關於表達式的定義是:「要產出值」,就會發現這樣的概念是不成立的,因為不能獨立作為變數值的程式碼,就不能算上表達式!

表達式、陳述式與 FP

為什麼我們需要在討論 FP 的途中,特別花一個篇幅來討論表達式與陳述式的差異呢?

誠如先前所提到的, FP 可以解決「JavaScript 」語言特性中不嚴謹的一些問題,特別是針對一些難以預期的值的改變、覆寫的情境。

透過上方的範例,我們理解到:表達式會回傳值,陳述式則是負責進行流程判斷;表達式可以獨立被賦予到變數中,或是參數做使用,但陳述式不行。

還記得我們先前所提到為什麼我們要在 JavaScript 中導入 FP 嗎?那是因為我們想要盡量避免不必要的錯誤。

而在 FP 是用什麼手段,讓 JavaScript 是弱型別的狀況下,依然保有可預期的結果?這裡我們先透露個小提示,在 FP 我們都是使用表達式來解決問題,至於為什麼?透過什麼樣的手段?為什麼我不在 FP 中使用陳述式?

以上的問題,我們會在後續的章節所提到,下一個章節,讓我們來小小複習一下目前為止所學習到的內容。

註解:

  1. 所謂的短路計算(Short-circuit evaluation)指的是透過 && 及 || 運算子的特性,直接將表達式給回傳的方式,舉例來說:
console.log(true && 3+1);
// 4
console.log(3+1 && true)
// true 

使用 && 運算子進行值的運算,當兩者皆為真值(Truthy Value)時,會回傳後者的回傳值,若有其中之一不是真值,則回傳 false

console.log(false || 3+1);
// 4
console.log(3+1 || undefined)
// 4

使用 || 運算子進行值的運算,會回傳優先讀取到的「真值」之回傳值,若沒有任何真值,則回傳 false

參考資料:

  1. Dr. Axel Rauschmayer - Expressions versus statements in JavaScript
  2. Ethan Brown - JavaScript 學習手冊 第三版 P.92

上一篇
Day 6 :JavaScript 型別與他們的地雷(3):函式是一等公民
下一篇
Day 8 :JavaScript 型別與他們的地雷(5):結語
系列文
致 JavaScript 開發者的 Functional Programming 新手指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言